package gui.border;

import java.awt.*;

/**
 *	@(#)PolygonBevelBorder.java
 *
 *	The <code>PolygonBevelBorder</code> class extends the built-in <code>BevelBorder</code>
 *	class to support polygonal borders. All the original features remain the same.
 *
 *	@author Grzegorz Kobiela
 *	@version 1.0 2007/9/11
 */

public class PolygonBevelBorder
extends javax.swing.border.BevelBorder
{
	/**
	 *	Creates a polygonal bevel border with the specified type and whose
	 *	colors will be derived from the background color of the component
	 *	passed into the paintBorder method.
	 *	@param type the type of bevel for the border
	 */
	public PolygonBevelBorder(int type) {
		super(type);
	}

	/**
	 *	Creates a polygonal bevel border with the specified type,
	 *	highlight and shadow colors.
	 *	@param type the type of bevel for the border
	 *	@param highlight the color to use for the bevel highlight
	 *	@param shadow the color to use for the bevel shadow
	 */
	public PolygonBevelBorder(int type, Color highlight, Color shadow) {
		super(type, highlight, shadow);
	}

	/**
	 *	Creates a polygonal bevel border with the specified type,
	 *	highlight and shadow colors.<br><br>
	 *	Note: The shadow inner and outer colors are
	 *	switched for a lowered bevel border.
	 *	@param type the type of bevel for the border
	 *	@param highlightOuterColor the color to use for the bevel outer highlight
	 *	@param highlightInnerColor the color to use for the bevel inner highlight
	 *	@param shadowOuterColor the color to use for the bevel outer shadow
	 *	@param shadowInnerColor the color to use for the bevel inner shadow
	 */
	public PolygonBevelBorder(int type, Color highlightOuterColor, Color highlightInnerColor, Color shadowOuterColor, Color shadowInnerColor) {
		super(type, highlightOuterColor, highlightInnerColor, shadowOuterColor, shadowInnerColor);
	}

	protected void paintRaisedBevel(Component c, Graphics g, int x, int y, int w, int h)  {
		if(!(c instanceof gui.Polygonal)) {
			super.paintRaisedBevel(c, g, x, y, w, h);
		} else {
			drawBorder(c, g, x, y, getHighlightOuterColor(c), getHighlightInnerColor(c), getShadowOuterColor(c), getShadowInnerColor(c));
		}
	}

	protected void paintLoweredBevel(Component c, Graphics g, int x, int y, int w, int h)  {
		if(!(c instanceof gui.Polygonal)) {
			super.paintLoweredBevel(c, g, x, y, w, h);
		} else {
			drawBorder(c, g, x, y, getShadowInnerColor(c), getShadowOuterColor(c), getHighlightOuterColor(c), getHighlightInnerColor(c));
		}
	}

	protected static void drawBorder(Component c, Graphics g, int x, int y, Color hoc, Color hic, Color soc, Color sic) {
		g.translate(x, y);
		Polygon p = ((gui.Polygonal)c).getPolygon();
		Color col = g.getColor();
		int a = (int)Math.signum(getArea(p));
		int x1, x2, y1, y2, dx, dy, fx, fy, n = p.npoints;
		for(int i = 1; i <= n; i++) {
			dx = (x1 = p.xpoints[i - 1]) - (x2 = p.xpoints[i % n]);
			dy = (y1 = p.ypoints[i - 1]) - (y2 = p.ypoints[i % n]);
			fx = dx * a;
			fy = dy * a;

			/* Draw western line */
			if(fx == 0 && fy > 0) {
				g.translate(x1, y1);
				g.setColor(hoc);
				g.drawLine(0, 0, 0, -dy);
				g.setColor(hic);
				g.drawLine(1, -a, 1, -dy + a);
				g.translate(-x1, -y1);
				continue;
			}

			/* Draw northern line */
			if(fx < 0 && fy == 0) {
				g.translate(x1, y1);
				g.setColor(hoc);
				g.drawLine(0, 0, -dx, 0);
				g.setColor(hic);
				g.drawLine(a, 1, -dx - a, 1);
				g.translate(-x1, -y1);
				continue;
			}

			/* Draw eastern line */
			if(fx == 0 && fy < 0) {
				g.translate(x1, y1);
				g.setColor(soc);
				g.drawLine(-1, a > 0 ? 0 : -1, -1, -dy + (a > 0 ? -1 : 0));
				g.setColor(sic);
				g.drawLine(-2, a > 0 ? 1 : -2, -2, -dy + (a > 0 ? -2 : 1));
				g.translate(-x1, -y1);
				continue;
			}

			/* Draw southern line */
			if(fx > 0 && fy == 0) {
				g.translate(x1, y1);
				g.setColor(soc);
				g.drawLine(a > 0 ? -1 : 0, -1, -dx + (a > 0 ? 0 : -1), -1);
				g.setColor(sic);
				g.drawLine(a > 0 ? -2 : 1, -2, -dx + (a > 0 ? 1 : -2), -2);
				g.translate(-x1, -y1);
				continue;
			}
		}
		g.setColor(col);
		g.translate(-x, -y);
	}

	protected static int getArea(Polygon p) {
		int s = 0;
		for(int i = 0; i < p.npoints - 1; i++) {
			s += p.xpoints[i] * p.ypoints[i + 1];
			s -= p.xpoints[i + 1] * p.ypoints[i];
		}
		return s / 2;
	}
}